﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Office = Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Configuration;
using System.Xml.Linq;
using System.IO;
using System.Threading;
using System.Reflection;
using System.Diagnostics;

namespace Out2Share
{
    public partial class TreeViewContainer : UserControl
    {
        protected static string CONFIGURE_STRING = "Click here to configure endpoint.";
        protected static ConfData ENDPOINT;
        TreeNodeCustomVar overNode;
        TreeNodeCustomVar targetNode;
        public delegate void AddListItem(XElement xElementWeb, XElement xElementList);
        public AddListItem addListItemDelegate;
        public delegate void UploadEnd(int nFiles);
        public UploadEnd uploadDelegate;
        public delegate void ErrorOnThread(string message);
        public ErrorOnThread ErrorOnThreadDelegate;
        public delegate void AddFolders(List<string> urls);
        public AddFolders AddFolderDelegate;
        public string currentFolder = "";
        
        string url;
        int savedImage;
        
        /// <summary>
        /// Get and Set Endpoint in configuration
        /// </summary>
        public ConfData Conf
        {
            get
            {
                if (ENDPOINT != null) return ENDPOINT;
                System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                if (config.AppSettings.Settings["ENDPOINT"] != null)
                {
                    ENDPOINT = new ConfData(config.AppSettings.Settings["ENDPOINT"].Value);
                }
                else
                {
                    ENDPOINT = new ConfData("CONFIGURATION_ENDPOINT_NAME=not configured;CONFIGURATION_LIBRARY=;CONFIGURATION_USER_NAME=;CONFIGURATION_USER_PWD=;CONFIGURATION_AUTH=;CONFIGURATION_PROXY_SET=False;CONFIGURATION_PROXY_ADDRESS=;CONFIGURATION_PROXY_USER=;CONFIGURATION_PROXY_PWD=;CONFIGURATION_FLAG=Follow up;CONFIGURATION_CATEGORY=Archive");
                }
                return ENDPOINT;
            }
            set
            {
                System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                if (config.AppSettings.Settings["ENDPOINT"] == null)
                {
                    config.AppSettings.Settings.Add("ENDPOINT", value.Serialize());
                }
                else
                {
                    config.AppSettings.Settings["ENDPOINT"].Value = value.Serialize();
                }
                config.Save(ConfigurationSaveMode.Modified);
                ENDPOINT = value;
            }
        }

        /// <summary>
        /// Initialization
        /// </summary>
        public TreeViewContainer()
        {
            InitializeComponent();
            this.Dock = DockStyle.Fill;
            this.treeView.AllowDrop = true;
            this.treeView.ImageList = this.imageList;
            this.treeView.DragEnter += new DragEventHandler(treeView_DragEnter);
            this.treeView.DragOver += new DragEventHandler(treeView_DragOver);
            this.treeView.DragLeave += new EventHandler(treeView_DragLeave);
            this.treeView.NodeMouseClick += new TreeNodeMouseClickEventHandler(treeView_NodeMouseClick);
            this.treeView.DragDrop += new DragEventHandler(treeView_DragDrop);
            addListItemDelegate = new AddListItem(AddListItemMethod);
            uploadDelegate = new UploadEnd(UploadEndMethod);
            ErrorOnThreadDelegate = new ErrorOnThread(ErrorOnThreadMethod);
            AddFolderDelegate = new AddFolders(AddFolderMethod);
            CreateRootNode();
        }

        /// <summary>
        /// Clear highlight from old node
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void treeView_DragLeave(object sender, EventArgs e)
        {
            if (overNode != null) overNode.BackColor = Color.Transparent;
            overNode = null;
        }

        /// <summary>
        /// Highlight current node and clear highlight from old one
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void treeView_DragOver(object sender, DragEventArgs e)
        {
            Point pos = treeView.PointToClient(new Point(e.X, e.Y)); 
            //Point pos = new Point(e.X, e.Y);
            TreeNodeCustomVar targetNode = (TreeNodeCustomVar)treeView.GetNodeAt(pos);
            if (targetNode != null)
            {
                if (overNode != null && overNode != targetNode)
                {
                    overNode.BackColor = Color.Transparent;
                    overNode = null;
                }
                targetNode.BackColor = Color.Yellow;
            }
            overNode = targetNode;
            return;
        }

        void treeView_DragDrop(object sender, DragEventArgs e)
        {
           
            if (overNode != null) overNode.BackColor = Color.Transparent;
            overNode = null;
            
            //wrap standard IDataObject in OutlookDataObject
            OutlookDataObject dataObject = new OutlookDataObject(e.Data);
            
            //get the names and data streams of the files dropped
            string[] filenames = (string[])dataObject.GetData("FileGroupDescriptorW");
            MemoryStream[] filestreams = (MemoryStream[])dataObject.GetData("FileContents");

            Point pos = treeView.PointToClient(new Point(e.X, e.Y)); 
            TreeNodeCustomVar _targetNode = (TreeNodeCustomVar)treeView.GetNodeAt(pos);
            if (_targetNode != null && targetNode == null)
            {
                string type = _targetNode.CustomAttributes["type"].ToString();
                if (type == "library" || type == "folder")
                {
                    targetNode = _targetNode;
                    savedImage = targetNode.ImageIndex;
                    targetNode.ImageIndex = 4;
                    targetNode.SelectedImageIndex = 4;

                    string url = targetNode.CustomAttributes["url"].ToString();
                    string rurl = targetNode.CustomAttributes["library"].ToString();
                    UploadThread upload = new UploadThread(this, filenames, filestreams,ENDPOINT, url, rurl,currentFolder);
                    Thread myThread = new Thread(new ThreadStart(upload.Run));
                    myThread.Start();
                }
            }
        }

        private void CreateRootNode()
        {
            
            if (treeView.Nodes.Count == 0)
            {
                string ep = Conf.ht["CONFIGURATION_ENDPOINT_NAME"].ToString();
                if (ep.EndsWith("/")) ep = ep.Substring(0, ep.Length - 1);
                TreeNodeCustomVar rootNode = new TreeNodeCustomVar(ep);
                treeView.Nodes.Add(rootNode);
                rootNode.CustomAttributes.Add("url", ep);
                rootNode.ImageIndex = 0;
                rootNode.SelectedImageIndex = 0;
                rootNode.CustomAttributes.Add("expanded", false);
                if (ep != TreeViewContainer.CONFIGURE_STRING)
                {
                    if (Conf.ht["CONFIGURATION_LIBRARY"].Trim().Length > 0)
                    {
                        rootNode.CustomAttributes.Add("type", "library");
                        rootNode.CustomAttributes.Add("library",  Conf.ht["CONFIGURATION_LIBRARY"].Trim());
                    }
                    else
                    {
                        rootNode.CustomAttributes.Add("type", "site");
                    }
                }
                else
                {
                    rootNode.CustomAttributes.Add("type", "none");
                }
                rootNode.ImageIndex = 0;
                rootNode.ContextMenuStrip = contextMenuStrip1;
            }
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            ConfData retVal = Conf;
            FormConfiguration fc = new FormConfiguration();
            fc.conf = retVal;
            if (fc.ShowDialog() == DialogResult.OK)
            {
                this.Conf = retVal;
                this.treeView.Nodes.Clear();
                this.CreateRootNode();
            }
        }

        private void treeView_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            Point pos = new Point(e.X, e.Y);
            TreeNodeCustomVar _targetNode = (TreeNodeCustomVar)treeView.GetNodeAt(pos);
            ExpandTreeNode(_targetNode);
        }

        private void ExpandTreeNode(TreeNodeCustomVar _targetNode)
        {
            bool expanded = (bool)_targetNode.CustomAttributes["expanded"];
            string type = _targetNode.CustomAttributes["type"].ToString();
            if (type == "site" && _targetNode != null && targetNode == null && !expanded)
            {
                targetNode = _targetNode;
                url = targetNode.CustomAttributes["url"].ToString();
                savedImage = targetNode.ImageIndex;
                targetNode.ImageIndex = 3;
                targetNode.SelectedImageIndex = 3;
                targetNode.TreeView.Refresh();
                NodeFinderThread finder = new NodeFinderThread(this, Conf, url);
                Thread myThread = new Thread(new ThreadStart(finder.Find));
                myThread.Start();
            }
            if ((type == "library" || type == "folder") && _targetNode != null && targetNode == null && !expanded)
            {
                targetNode = _targetNode;
                url = targetNode.CustomAttributes["url"].ToString();
                string library = targetNode.CustomAttributes["library"].ToString();


                savedImage = targetNode.ImageIndex;
                targetNode.ImageIndex = 3;
                targetNode.SelectedImageIndex = 3;
                targetNode.TreeView.Refresh();
                NodeFinderThread finder = new NodeFinderThread(this, Conf, url, library);
                Thread myThread = new Thread(new ThreadStart(finder.FindFolder));
                myThread.Start();
            }
        }

        /// <summary>
        /// Calback function from Thread NodeFinderThread
        /// </summary>
        /// <param name="xElementWeb"></param>
        /// <param name="xElementList"></param>
        private void AddListItemMethod(XElement xElementWeb, XElement xElementList)
        {
            foreach (XElement el1 in xElementWeb.Descendants())
            {
                string title = el1.Attribute("Title").Value;
                TreeNodeCustomVar el1Node = new TreeNodeCustomVar(title);
                el1Node.ImageIndex = 1;
                el1Node.SelectedImageIndex = 1;
                el1Node.CustomAttributes["expanded"] = false;
                el1Node.CustomAttributes["type"] = "site";
                el1Node.CustomAttributes["url"] = el1.Attribute("Url").Value;

                targetNode.Nodes.Add(el1Node);
                targetNode.CustomAttributes["expanded"] = true;
                el1Node.ContextMenuStrip = contextMenuStrip1;
            }

            foreach (XElement el1 in xElementList.Descendants())
            {
                string title = el1.Attribute("Title").Value;
                string hidden = el1.Attribute("Hidden").Value;
                if (hidden == "False")
                {
                    TreeNodeCustomVar el1Node = new TreeNodeCustomVar(title);
                    el1Node.ImageIndex = 5;
                    el1Node.SelectedImageIndex = 5;
                    el1Node.CustomAttributes["expanded"] = false;
                    el1Node.CustomAttributes["type"] = "library";
                    el1Node.CustomAttributes["url"] = url;

                    // try to find library name
                    string rurl = el1.Attribute("DefaultViewUrl").Value.ToString();
                    //if (url.IndexOf("/", 8) > 0)
                    if (url.Length>8 && url.IndexOf("/", 8) > 0)
                    {
                        string url1 = url.Substring(url.IndexOf("/", 8));
						if (url1.EndsWith("/"))
						{
							rurl = rurl.Substring(url1.Length);
						}
						else {
							rurl = rurl.Substring(url1.Length+1);
                        }
                        rurl = rurl.Substring(0, rurl.IndexOf("/"));
                    }
                    else {
                        rurl = "";
                    }
                    el1Node.CustomAttributes["library"] = rurl;
                    el1Node.CustomAttributes["id"] = el1.Attribute("ID").Value;

                    targetNode.Nodes.Add(el1Node);
                    targetNode.CustomAttributes["expanded"] = true;
                    el1Node.ContextMenuStrip = contextMenuStrip1;
                }
            }
            targetNode.ImageIndex = savedImage;
            targetNode.SelectedImageIndex = savedImage;
            targetNode = null;
        }

        /// <summary>
        /// Calback function from Thread NodeFinderThread
        /// </summary>
        /// <param name="xElementFolder"></param>
        private void AddFolderMethod(List<string> urls) {
            if (urls.Count > 0)
            {
                foreach (string folder in urls)
                {
                    string title = folder;

                    TreeNodeCustomVar el1Node = new TreeNodeCustomVar(title.Substring(title.LastIndexOf("/")+1));
                    el1Node.ImageIndex = 2;
                    el1Node.SelectedImageIndex = 2;
                    el1Node.CustomAttributes["expanded"] = false;
                    el1Node.CustomAttributes["type"] = "folder";
                    el1Node.CustomAttributes["url"] = url;

                    el1Node.CustomAttributes["library"] = folder;

                    targetNode.Nodes.Add(el1Node);
                    el1Node.ContextMenuStrip = contextMenuStrip1;
                }
            }
            targetNode.CustomAttributes["expanded"] = true;
            targetNode.ImageIndex = savedImage;
            targetNode.SelectedImageIndex = savedImage;
            targetNode = null;
        } 

        /// <summary>
        /// Calback function from Thread UploadThread
        /// </summary>
        /// <param name="nFiles"></param>
        private void UploadEndMethod(int nFiles) {
            if (nFiles > 1)
            {
                MessageBox.Show("" + nFiles + " files archived", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("" + nFiles + " file archived", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            targetNode.ImageIndex = savedImage;
            targetNode.SelectedImageIndex = savedImage;
            targetNode = null;

            ThisAddIn.GetApplication(Conf.ht["CONFIGURATION_FLAG"], Conf.ht["CONFIGURATION_CATEGORY"]);


        }
        
        /// <summary>
        /// Calback function from Threads
        /// </summary>
        /// <param name="message"></param>
        private void ErrorOnThreadMethod(string message) {
            MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            if (targetNode != null)
            {
                targetNode.ImageIndex = savedImage;
                targetNode.SelectedImageIndex = savedImage;
                targetNode = null;
            }
        }

        /// <summary>
        /// Save the current TreeNode selected for context menu
        /// </summary>
        private TreeNodeCustomVar tncv;
        
        /// <summary>
        /// On context menu open
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void contextMenuStrip1_Opened(object sender, EventArgs e)
        {
            TreeView tv = (TreeView)(sender as ContextMenuStrip).SourceControl;
            tncv = (TreeNodeCustomVar)tv.SelectedNode;
        }
        
        /// <summary>
        /// Context Menu Refresh click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool expanded = (bool)tncv.CustomAttributes["expanded"];
            if (expanded)
            {
                while (tncv.Nodes.Count > 0)
                {
                    tncv.Nodes[0].Remove();
                }
            }
            tncv.CustomAttributes["expanded"] = false;
            ExpandTreeNode(tncv);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string url = tncv.CustomAttributes["url"].ToString();
                string type = tncv.CustomAttributes["type"].ToString();
                if (type == "library" || type == "folder")
                {
                    string rurl = tncv.CustomAttributes["library"].ToString();
                    url += "/"+rurl;
                }
                ProcessStartInfo sInfo = new ProcessStartInfo(url);
                Process.Start(sInfo);
            }
            catch (Exception) { }
        }
    }
}
